const vscode = require('vscode');
const fs = require('fs');
const util = require('../util');

/**
 * services自动提示实现，当输入 this.proxy.xxx时自动提示
 * @param {*} document 
 * @param {*} position 
 * @param {*} token 
 * @param {*} context 
 */
function provideCompletionItems(document, position, token, context) {
    const line        = document.lineAt(position);
    const projectPath = util.getProjectPath(document);

    // 只截取到光标位置为止，防止一些特殊情况
    const lineText = line.text.substring(0, position.character);
    // 简单匹配，只要当前光标前的字符串为`this.proxy.`都自动带出所有的services
    if(/(^|=| )\w+\.proxy\.$/g.test(lineText)) {
        // 这里有2种实现方法，一种是列出 app/proxy 下的所有文件，
        // 一种是读取 config/proxy.js文件里面的所有services，这里采用第一种方法
        const files = fs.readdirSync(`${projectPath}/app/proxy`);
        return files.map(file => {
            file = util.lowerFirstLeter(file).replace(/\.js$/g, '');
            // vscode.CompletionItemKind 表示提示的类型
            return new vscode.CompletionItem(file, vscode.CompletionItemKind.Field);
        })
    }
    // 如果匹配到 this.proxy.xxx.
    const regResult = /(^|=| )\w+\.proxy\.([^.]+?)\.$/g.exec(lineText);
    if (!regResult) return;
    // 这里特别要注意，vscode有个比较坑爹的地方，当require一个function进来时，
    // 虽然打印在控制台显示为null，但其实是有值的，不知道的人很容易被误导
    const serviceName = util.upperFirstLetter(regResult[2]);
    if (!serviceName) return;
    const proxyFile = require(`${projectPath}/app/proxy/${serviceName}.js`);
    // 导入的代理文件其实是一个function，要执行必须传一个app参数
    // 这里定义的app仅仅是为了让函数执行时不报错
    const app = {
        config: {},
        hsfClient: {
            createConsumer: function() {
                return true;
            }
        },
        Proxy: class{}
    }
    let methods = Reflect.ownKeys(proxyFile(app).prototype);
    // 这里返回的所有方法中包含 constructor 方法，所以需要剔除
    methods = methods.filter(method => method !== 'constructor');
    return methods.map(item => new vscode.CompletionItem(item.toString(), vscode.CompletionItemKind.Function));
}

/**
 * 光标选中当前自动补全item时触发动作，一般情况下无需处理
 * @param {*} item 
 * @param {*} token 
 */
function resolveCompletionItem(item, token) {
    return null;
}

module.exports = function(context) {
    // 注册代码建议提示，只有当按下“.”时才触发
    context.subscriptions.push(vscode.languages.registerCompletionItemProvider('javascript', {
        provideCompletionItems,
        resolveCompletionItem
    }, '.'));
};